package com.wthink.card;

import android.content.Context;
import android.os.Handler;
import android.util.Log;

import com.wthink.card.Thread.SocketFrameProcThread;
import com.wthink.card.models.GMBInfoBundle;
import com.wthink.card.models.ShdFrameBundle;
import com.wthink.card.models.TcpClientFrameBundle;
import com.wthink.card.models.Utils;
import com.wthink.hzgj.Constants;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;


public class ShdThread extends Thread {
	private static final String TAG = "ShdThread";
	// global definition ----------------------------------------------
	public static final int VCA_READ_TIMEOUT = 3000;	//ms

	// error reason
	public static final int ER_NO_ERROR = 0;
	public static final int ER_REMOTE_SERVER_CLOSE = 0;	// 服务器关闭连接
	public static final int ER_SYSTEM_EXCEPTION = -1;		// 系统内部异常
	public static final int ER_NO_ACTIVE_NETWORK = -2;	// 没有可用的网络
	public static final int ER_REMOTE_SERVER_ERROR = -3;	//	服务器内部错误
	public static final int ER_CONN_TIMEOUT = -4;		// 网络中断或连接超时
	public static final int ER_WRONG_FRAME = -5;  	// 数据帧解析出错
	public static final int ER_INVALID_SERVER_NAME = -6;  	//
	public static final int ER_SEND_FAILE = -7;  	// 	数据发送失败

	public static final int ER_IO_EXCEPTION = -8;  	// 	IO错误,写文件失败?可能磁盘空间已满..
	public static final int ER_CONN_RESET_BY_PEER = -9;  	// 连接被服务器重置，可能网络较差
	//You do not have read/write permission to the serial port
	public static final int ER_PERMISSION_DENY = -10;
	//The serial port can not be opened for an unknown reason
	public static final int ER_SERIAL_UNKNOWN = -11;
	//Please configure your serial port first.
	public static final int ER_SERIAL_PARA = -12;
	public static final int NR_CLOSED = 0;	  // server close connection
	public static final int NR_NEED_MORE = 1;	  	//  need to read more
	public static final int NR_READY_FOR_PROCESS = 2;	 // 	frame is fully loaded, can be processed now.

	// vca proto state
	public static final int S_NOT_LOG_IN = 0;		// 初始状态,
	public static final int S_LOGGED_IN = 1;
	public static final int S_DISCONNECTED = 2;	// 网络异常中断,导致掉线

	public static final int MAX_VCA_BUF_LEN = 8192;  //8k buffer
	public static final int MAX_VCA_BUF_UPDATE_LEN = 9216;  //9k buffer
	public static final int BUNDLE_HEARDER_LEN = 3;	// bundle header len ..
	public static final int BUNDLE_TAIL_LEN = 2;

	public static final int MAX_BUNDLE_LEN = 256;

	public static int	vcaState = S_NOT_LOG_IN;
	public static int	vcaLastError = ER_NO_ERROR;
	public boolean bVcaProtoRunning = true;


	//judge over speed
	private static long iRecordSpeed = 0;
	private static long iRecordLastOverSpeedTime = 0;

	//------------------------------------------------------------

	protected ByteBuffer shdFrameBuf;
	protected byte[] vcaBufRaw;

	protected ByteBuffer shdFrameBufTcp;
	protected byte[] vcaBufRawTcp;

	protected int	vfbDataLen = 0; // the real data len in the frame buffer.
	protected int	vfbCapacity = MAX_VCA_BUF_UPDATE_LEN;
	protected int	vfbDataLeft = 0; // the real data size that hasnt been processed yet.
	protected int	vfbCapacityLeft = 0; // the left size of fb

	protected int	vfbDataLenTcp = 0; // the real data len in the frame buffer.
	protected int	vfbCapacityTcp = MAX_VCA_BUF_LEN;
	protected int	vfbDataLeftTcp = 0; // the real data size that hasnt been processed yet.
	protected int	vfbCapacityLeftTcp = 0; // the left size of fb

	public static ShdFrameBundle currFrameBundle;

	public static boolean		informUIWhenFinally = false;
	private Handler mHandler;

	protected boolean chk = false;
	protected int   mChk = 0;
	public static TcpClientFrameBundle currFrameBundleTcp;

	//预防主机升级时不给操作屏发送升级成功标志，屏做判断收到10个0xa0后判断是否还在显示框
	private int mUpdate = 0;
	private boolean readLenFlag=false;


	public ShdThread(Context ctx,String tn, Handler h){

		mHandler = h;
		// var inits
		if(shdFrameBufTcp == null){
			shdFrameBufTcp =  ByteBuffer.allocate(MAX_VCA_BUF_LEN);
			vcaBufRawTcp = shdFrameBufTcp.array();
		}
		if(shdFrameBuf == null){
			shdFrameBuf =  ByteBuffer.allocate(MAX_VCA_BUF_UPDATE_LEN);
			vcaBufRaw = shdFrameBuf.array();
		}
	}

	public ShdThread(Context ctx,String tn){
		// var inits
		if(shdFrameBufTcp == null){
			shdFrameBufTcp =  ByteBuffer.allocate(MAX_VCA_BUF_LEN);
			vcaBufRawTcp = shdFrameBufTcp.array();
		}
		if(shdFrameBuf == null){
			shdFrameBuf =  ByteBuffer.allocate(MAX_VCA_BUF_UPDATE_LEN);
			vcaBufRaw = shdFrameBuf.array();
		}
	}

	public ShdThread(Context ctx, String tn, Handler h,
					 Socket s) {
		mHandler = h;
		// var inits
		if (shdFrameBufTcp == null) {
			shdFrameBufTcp = ByteBuffer.allocate(MAX_VCA_BUF_LEN);
			vcaBufRawTcp = shdFrameBufTcp.array();
		}
		if(shdFrameBuf == null){
			shdFrameBuf =  ByteBuffer.allocate(MAX_VCA_BUF_UPDATE_LEN);
			vcaBufRaw = shdFrameBuf.array();
		}
	}

	public void sendMsgToHandler(int what) {
		if(mHandler == null)
			return;
		mHandler.sendMessage(mHandler.obtainMessage(what));
	}

	public void sendMsgToHandler(int what,int prm1,int prm2) {
		if(mHandler == null)
			return;
		mHandler.sendMessage(mHandler.obtainMessage(what,prm1,prm2));
	}

	public void sendMsgToHandlerWithDelay(int what,int delay){
		if(mHandler == null)
			return;
		mHandler.sendMessageDelayed(mHandler.obtainMessage(what),delay);
	}

	public void sendMsgToHandlerObj(int what,int prm1,int prm2,Object obj){
		if(mHandler == null)
			return;
		mHandler.sendMessage(mHandler.obtainMessage(what,prm1,prm2, obj));
	}

	public void shdStop(){
		bVcaProtoRunning = false;
	}

	public int packMainBoardNormalFrm(int type, byte[] data, int datalen, ByteBuffer out){
		if(datalen + BUNDLE_HEARDER_LEN + BUNDLE_TAIL_LEN > MAX_BUNDLE_LEN){
			return ER_SEND_FAILE;
		}
		out.put((byte)0x24);
		out.put((byte)type);
		out.put((byte)(datalen + BUNDLE_TAIL_LEN));
		if(datalen > 0 && data != null){
			out.put(data, 0, datalen);
		}
		out.put((byte)0x00);
		out.put((byte)0xff);
		return out.position();
	}

	public int packBoardNormalClient(int type, byte[] data, int datalen,
									 ByteBuffer out, int devicetype) {
		if (datalen + BUNDLE_HEARDER_LEN + BUNDLE_TAIL_LEN > MAX_BUNDLE_LEN) {
			return ER_SEND_FAILE;
		}

		out.put((byte) 0x7E);
		out.put(intToByte(datalen + 5));	//数据长度
		out.put((byte) devicetype);			//设备类型
		out.put(intToByte(type));
		if (datalen > 0 && data != null) {
			out.put(data, 0, datalen);
		}
		out.put((byte) update_CRC(data, intToByte(datalen + 5), type, devicetype, datalen));
		out.put((byte) 0x7F);
		return out.position();
	}

	static int update_CRC(byte[] data, byte[] length, int type, int devicetype,int len) // 校验位 异或校验
	{
		int checksum = 0;
		checksum ^= length[0];
		checksum ^= length[1];
		checksum ^= devicetype;
		checksum ^= type;
		if (data != null) {
			for (int i = 0; i < len; i++) {
				checksum ^= data[i];
			}
		}
		return checksum & 0xff;
	}

	public byte[] intToByte(int i) { // int转byte 高前，低后
		byte[] abyte0 = new byte[2];
		abyte0[0] = (byte) (0xff & i >> 8);
		abyte0[1] = (byte) ((0xff & i));
		return abyte0;
	}

	public int intFromByte(byte[] temp) { // byte转int
		int value = 0;
		value = (((temp[0] & 0xff) << 8) | (temp[1] & 0xff));
		return value;
	}

	public int readAndParseShdFrameTcp(InputStream vcaIS) {
		int readLen = 0; // read len from sock stream..

		// for bundle header
		int startFlag;
		int fLen;

		boolean bReadMore = false;
		boolean bNewBundle = false;
		vfbDataLeftTcp = vfbDataLenTcp - shdFrameBufTcp.position();
		vfbCapacityLeftTcp = vfbCapacityTcp - vfbDataLenTcp;
		// the framebuf capacity is over, we need to reset the frame buffer.
		if (vfbCapacityLeftTcp == 0) {
			// Log.i(threadName,"frame buf reset!");
			shdFrameBufTcp.compact(); // move left data to pos zero (if have..)
			// fix the postion
			shdFrameBufTcp.rewind();
			// adjust data len
			vfbDataLenTcp = vfbDataLeftTcp;
			vfbDataLeftTcp = vfbDataLenTcp - shdFrameBufTcp.position();
			vfbCapacityLeftTcp = vfbCapacityTcp - vfbDataLenTcp;
		}

		if (vfbDataLeftTcp < 0 || vfbCapacityLeftTcp < 0) { // over flow .....
			return ER_SYSTEM_EXCEPTION;
		}

		if (currFrameBundleTcp != null) {
			switch (currFrameBundleTcp.getFrameBundleState()) {
				case TcpClientFrameBundle.FS_FRM_READY: // ready to be processed
					return 0;
				case TcpClientFrameBundle.FS_NOT_READY: // need to read more data
					bReadMore = true;
					break;
				case TcpClientFrameBundle.FS_BODY_READY: // need to read tail
					bReadMore = true;
					break;
				default:
					currFrameBundleTcp = null;
					bNewBundle = true;
					break;
			}
		} else {
			bNewBundle = true;
		}
		// read new frame from frame buffer
		// test wheath fb has the data or not...
		if (bNewBundle && (vfbDataLeftTcp < BUNDLE_HEARDER_LEN)) {
			bReadMore = true; // ao, we need the data from sock stream
		}

		// read data from socket
		if (bReadMore) {
			if (vcaIS == null)
				return ER_SYSTEM_EXCEPTION;

			try {
				readLen = vcaIS.read(vcaBufRawTcp, vfbDataLenTcp, vfbCapacityLeftTcp);
			} catch (SocketTimeoutException e) {
				return NR_NEED_MORE;
			} catch (SocketException e) {
				return ER_CONN_RESET_BY_PEER;
			} catch (IOException e) {
				e.printStackTrace();
				return ER_SYSTEM_EXCEPTION;
			}

			if (readLen < 0) // remote close
				return NR_CLOSED;

			if (readLen == 0) // we need more
				return NR_NEED_MORE;
			vfbDataLenTcp += readLen;
			vfbDataLeftTcp = vfbDataLenTcp - shdFrameBufTcp.position();
		}

		if (bNewBundle) {
			if (vfbDataLeftTcp < BUNDLE_HEARDER_LEN)
				return NR_NEED_MORE;

			// get frame start flag
			startFlag = shdFrameBufTcp.get();
			if (startFlag != 0x7E) {
				return ER_WRONG_FRAME;
			}

			// 数据长度（不含起止符）
			byte[] bLen = new byte[2];
			shdFrameBufTcp.get(bLen);
			fLen = intFromByte(bLen);

			// load frame body
			currFrameBundleTcp = new TcpClientFrameBundle();
			currFrameBundleTcp.setFrameBundleBodyLen(fLen);
			currFrameBundleTcp.prepareFrameBundleBody();
			vfbDataLeftTcp = vfbDataLenTcp - shdFrameBufTcp.position();
		}

		try{
			if (currFrameBundleTcp != null) {
				int ret = currFrameBundleTcp.fillFrameBundleBody(shdFrameBufTcp, vfbDataLeftTcp);
				vfbDataLeftTcp = vfbDataLenTcp - shdFrameBufTcp.position();
				if (ret == 0) {
					return NR_READY_FOR_PROCESS;
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return NR_NEED_MORE;
	}

	public int readAndParseShdFrame(InputStream vcaIS){
		int readLen = 0;   // read len from sock stream..

		// for bundle header
		int startFlag;
		int fSubType;
		int fMainType;
		int fLen;

		boolean	bReadMore = false;
		boolean	bNewBundle = false;

		vfbDataLeft = vfbDataLen - shdFrameBuf.position();
		vfbCapacityLeft = vfbCapacity - vfbDataLen;

		// the framebuf capacity is over, we need to reset the frame buffer.
		if(vfbCapacityLeft == 0){

			//Log.i(threadName,"frame buf reset!");
			shdFrameBuf.compact();	// move left data to pos zero (if have..)
			// fix the postion
			shdFrameBuf.rewind();
			// adjust data len
			vfbDataLen = vfbDataLeft;

			vfbDataLeft = vfbDataLen - shdFrameBuf.position();
			vfbCapacityLeft = vfbCapacity - vfbDataLen;
		}


		if(vfbDataLeft < 0 || vfbCapacityLeft < 0){  // over flow .....
			return ER_SYSTEM_EXCEPTION;
		}

		if(currFrameBundle != null)
		{
			switch(currFrameBundle.getFrameBundleState()){
				case ShdFrameBundle.FS_FRM_READY: // ready to be processed
					return 0;
				case ShdFrameBundle.FS_NOT_READY: // need to read more data
					bReadMore = true;
					break;
				case ShdFrameBundle.FS_BODY_READY: // need to read tail
					bReadMore = true;
					break;
				default:
					currFrameBundle = null;
					bNewBundle = true;
					break;
			}
		}else{
			bNewBundle = true;
		}
		// read new frame from frame buffer
		// test wheath fb has the data or not...
		if(bNewBundle && (vfbDataLeft < BUNDLE_HEARDER_LEN)){
			bReadMore = true;  // ao, we need the data from sock stream
		}
		// 	read data from socket
		if(bReadMore){
			if(vcaIS == null)	return ER_SYSTEM_EXCEPTION;

			try {
				readLen = vcaIS.read(vcaBufRaw,vfbDataLen,// vfbDataLen == offset in frame buf
						vfbCapacityLeft);
			} catch (SocketTimeoutException e) {
				// TODO Auto-generated catch block
				//Log.e(threadName,"socket read timeout");
				return NR_NEED_MORE;
			} catch (SocketException e) {
				// TODO Auto-generated catch block
				//Log.e(threadName,"Connection reset by peer ??");
				return ER_CONN_RESET_BY_PEER;
			}catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				//Log.e(threadName,"Read io exception ....");
				return ER_SYSTEM_EXCEPTION;
			}

			if(readLen < 0) // remote close
				return NR_CLOSED;

			if(readLen == 0) // we need more
				return NR_NEED_MORE;

			vfbDataLen += readLen;
			vfbDataLeft = vfbDataLen - shdFrameBuf.position();

		}

		if(bNewBundle){

			if(vfbDataLeft < BUNDLE_HEARDER_LEN)
				return NR_NEED_MORE;

			// get frame start flag
			startFlag = shdFrameBuf.get();
			if(startFlag != 0x24){
				return ER_WRONG_FRAME;
			}

			fSubType = shdFrameBuf.get() & 0xff;
			if(!ShdFrameBundle.isValidFrameBundle(fSubType)){
				return ER_WRONG_FRAME;
			}

			fLen = shdFrameBuf.get() & 0xff;
			fLen -= 2;
			currFrameBundle = new ShdFrameBundle(fSubType);

			//load frame body
			if(fLen<0){
				fLen = 0;
			}
			currFrameBundle.setFrameBundleBodyLen(fLen);
			currFrameBundle.prepareFrameBundleBody();

			vfbDataLeft = vfbDataLen - shdFrameBuf.position();
		}


		if(currFrameBundle != null){
			if(currFrameBundle.getFrameBundleState() == ShdFrameBundle.FS_NOT_READY){
				currFrameBundle.fillFrameBundleBody(shdFrameBuf,vfbDataLeft);
				vfbDataLeft = vfbDataLen - shdFrameBuf.position();
			}
			if(currFrameBundle.getFrameBundleState() == ShdFrameBundle.FS_BODY_READY){
				if(vfbDataLeft >= BUNDLE_TAIL_LEN){
					fMainType = shdFrameBuf.get(); // skip chksum
					fMainType = shdFrameBuf.get() & 0xff;
					currFrameBundle.setFrameBundleMainType(fMainType);
					vfbDataLeft = vfbDataLen - shdFrameBuf.position();
					currFrameBundle.setFrameBundleState(ShdFrameBundle.FS_FRM_READY);
					return NR_READY_FOR_PROCESS;
				}
			}


		}

		return NR_NEED_MORE;
	}

	public int processShdFrameBundleTcp() {
		if (currFrameBundleTcp == null) {
			return 0;
		}
		currFrameBundleTcp.setFrameBundleState(TcpClientFrameBundle.FS_PROCESSED);
		return processShdGpsmainboardFrameBundleTcp();
	}

	public int processShdFrameBundle(){
		if(currFrameBundle == null) return 0;
		currFrameBundle.setFrameBundleState(ShdFrameBundle.FS_PROCESSED);
		if(currFrameBundle.isGpsmainboardFrameBundle()){//0x0a
			return processShdGpsmainboardFrameBundle();
		}
		else{
			return 0;
		}
	}

	/**
	 * 	蓝牙模块：0x00
	 *	控制模块：0x01
	 *	IC卡模块：0x02
	 *	透传：0x03
	 *	收音机模块：0x04
	 *	DVD模块: 0x05
	 */
	public int processShdGpsmainboardFrameBundleTcp() {
		int result = 0;
		ByteBuffer frameBuf = null;
		byte[] frameBundleBody = currFrameBundleTcp.getFrameBundleBody();
		if (frameBundleBody == null) {
			return ER_WRONG_FRAME;
		}
		frameBuf = ByteBuffer.wrap(frameBundleBody);
		if (frameBuf == null)
			return ER_WRONG_FRAME;
		int frameDevType = frameBuf.get() & 0xff;	//设备类型
		switch(frameDevType){
			case 0x00:		//蓝牙模块协议帧
				break;
			case 0x01:		//控制模块协议帧
				getModuleFrameBundle(frameBuf);
				break;
			case 0x02:		//IC卡模块
				getIcCardFrameBundle(frameBuf);
				break;
			case 0x03:		//数据透传
				break;
			case 0x04:		//收音机
				break;
			case 0x05:		//DVD模块
				break;
			case 0x06:		//
				break;
			default:
				break;
		}
		return result;
	}


	/**
	 * 控制模块协议帧
	 */
	private void getModuleFrameBundle(ByteBuffer frameBuf){
		try {
			int frameType;
			String temStr;
			int result = 0;
			int length;
			int type;
			byte[] tempByte;
			if(frameBuf.remaining() <= 1)
				return;
			byte[] byteStr = new byte[2];
			frameBuf.get(byteStr);
			//帧类型
			frameType = Utils.byteArrayInt(byteStr);
			//处理结果
			if(frameBuf.remaining() <= 0)
				return;
			if(frameType != 0x0006){
				result = frameBuf.get() & 0xff;
				GMBInfoBundle.SetSocketResult(result);
			}

			switch(frameType){
				case 0x0001:	//模块控制请求/应答
					break;
				case 0x0002:
					break;
				case 0x0003:	//内核版本获取
					if(result == 0x02)	//获取失败
						return;
					type  = frameBuf.get() & 0xff;
					if(type == 0){				//boot版本
						length = frameBuf.get() & 0xff;
						tempByte = new byte[length];
						frameBuf.get(tempByte);
						temStr = new String(tempByte, "GB2312");
						GMBInfoBundle.SetSocketAppBoot(temStr);
					}else if(type == 1){		//kernel版本
						length = frameBuf.get() & 0xff;
						tempByte = new byte[length];
						frameBuf.get(tempByte);
						temStr = new String(tempByte, "GB2312");
						GMBInfoBundle.SetSocketAppKernel(temStr);
					}else if(type == 2){		//lk版本
						length = frameBuf.get() & 0xff;
						tempByte = new byte[length];
						frameBuf.get(tempByte);
						temStr = new String(tempByte, "GB2312");
						GMBInfoBundle.SetSocketAppLk(temStr);
					}
					break;
				case 0x0004:
					break;
				case 0x0005:
					type  = frameBuf.get() & 0xff;
					if(type == 0){				//补丁结果
						length = frameBuf.get() & 0xff;  //返回补丁结果
						GMBInfoBundle.SetSocketTouchCalibration(result);
						if(length == 2){
							GMBInfoBundle.SetSocketTouchCalibration(0);
						}
					}else if(type == 1){		//触摸版本
						length = frameBuf.get() & 0xff;  //返回触摸版本
						if(result != 2)
							GMBInfoBundle.SetSocketTouchVer(length);
					}
					break;
				case 0x0006:	//摄像头状态
					break;
			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * IC卡模块
	 */
	private void getIcCardFrameBundle(ByteBuffer frameBuf){
		try {
			int frameType;
			String temStr;
			int result;
			byte[] byteStr = new byte[2];
			frameBuf.get(byteStr);
			//帧类型
			frameType = Utils.byteArrayInt(byteStr);
			//处理结果
			result = frameBuf.get() & 0xff;
			GMBInfoBundle.SetSocketResult(result);

			Log.d(TAG, "帧类型-->"+frameType);

			switch(frameType){
				case 0x0001:	//IC卡初始化请求/应答
					break;
				case 0x0002:	//IC卡卡号请求/应答
					if(result == 0x01){
						byte[] byteCard = new byte[8];
						frameBuf.get(byteCard);
						temStr = new String(byteCard, "GB2312");
						SocketFrameProcThread.mStrCardId.delete(0, SocketFrameProcThread.mStrCardId.length());
						SocketFrameProcThread.mStrCardId.append(temStr);

						if(frameBuf.remaining()> 1){		//（日检卡，司机卡）
							byte[] byteCard1 = new byte[2];
							frameBuf.get(byteCard1);
							temStr = new String(byteCard1, "GB2312");
							SocketFrameProcThread.mStrCardId.append(temStr);
						}
						sendMsgToHandler(Constants.UI_RC522);
					}else{
						System.out.println("0x0002   应答失败");
					}

					break;
				case 0x0003:	//IC卡域读取请求及/应答
					break;
				case 0x0004:	//IC卡域写入请求及/应答
					break;
				case 0x0005:	//IC卡卡号请求/应答（0005H）
					break;
			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	public int intFromByte1(byte temp) { // byte转int
		int value = 0;
		value = (temp & 0xff);
		return value;
	}

	public int intFromByte2(byte temp,byte temp1) { // byte转int
		int value = 0;
		value = (temp & 0xff) * 256;
		value += (temp1 & 0xff);
		return value;
	}


	public byte[] getSubBytes(byte[] src, int begin, int count) {		//截取byte数组
		byte[] bs = new byte[count];
		for (int i=begin; i<begin+count; i++) bs[i-begin] = src[i];
		return bs;
	}

	public int processShdGpsmainboardFrameBundle(){
		ByteBuffer frameBuf = null;

		frameBuf = ByteBuffer.wrap(currFrameBundle.getFrameBundleBody());
		if(frameBuf == null)
			return ER_WRONG_FRAME;

		try{
			StringBuilder result = new StringBuilder();
			int tempInt=0;

			switch(currFrameBundle.getFrameBundleSubType()){
				case ShdFrameBundle.S_TYPE_FT_RECVGPS:

					int iTimeChange = 0;
					int iAllowSpeed = 0;
					int iNowSpeed = 0;
					if(currFrameBundle.getFrameBundleBodyLen() < 27){
						return ER_WRONG_FRAME;
					}

					//hour
					result.delete(0, result.length());
					result.append(String.format("%x", frameBuf.get() & 0xff));
					try{
						if((tempInt = Integer.parseInt(result.toString())) <= 24 ){
							if(GMBInfoBundle.SetGpsTimeHour(tempInt) == 0)
								iTimeChange = 1;
						}
					}catch(NumberFormatException  e){
						Log.e(TAG, "===hour input err===");
					}

					//minute
					result.delete(0, result.length());
					result.append(String.format("%x", frameBuf.get() & 0xff));
					try{
						if((tempInt = Integer.parseInt(result.toString())) <= 60 ){
							if(GMBInfoBundle.SetGpsTimeMin(tempInt) == 0)
								iTimeChange = 1;
						}
					}catch(NumberFormatException  e){
						Log.e(TAG, "===minute input err===");
					}

					//skip sec
					result.delete(0, result.length());
					result.append(String.format("%x", frameBuf.get() & 0xff));
					try{
						if((tempInt = Integer.parseInt(result.toString())) <= 60 ){
							if(GMBInfoBundle.SetGpsTimeSecond(tempInt) == 0)
								iTimeChange = 1;
						}
					}catch(NumberFormatException  e){
						Log.e(TAG, "===minute input err===");
					}

					int[] byteLong = {frameBuf.get() & 0x7f,frameBuf.get() & 0xff,frameBuf.get() & 0xff,frameBuf.get() & 0xff};
					if(byteLong.length < 3){
						return ER_WRONG_FRAME;
					}
					GMBInfoBundle.SetGpsLong(byteLong);
					int[] byteLat = {frameBuf.get() & 0x7f,frameBuf.get() & 0xff,frameBuf.get() & 0xff,frameBuf.get() & 0xff};
					if(byteLat.length < 3){
						return ER_WRONG_FRAME;
					}
					GMBInfoBundle.SetGpsLat(byteLat);

					//net type
					frameBuf.get();

					//csq
					frameBuf.get();

					//skip
					int iOverSpdAllowTime = frameBuf.get() & 0xff;
					if(iOverSpdAllowTime < 3)
						iOverSpdAllowTime = 3;


					//skip
					frameBuf.get();

					//year
					result.delete(0, result.length());
					result.append(String.format("%x", frameBuf.get() & 0xff));
					try{
						if((tempInt = Integer.parseInt(result.toString())) <= 99 ){
							if(GMBInfoBundle.SetGpsDateYear(2000 + tempInt) == 0)
								iTimeChange = 1;
						}
					}catch(NumberFormatException  e){
						Log.e(TAG, "===year speed input err===");
					}

					//month
					result.delete(0, result.length());
					result.append(String.format("%x", frameBuf.get() & 0xff));
					try{
						if((tempInt = Integer.parseInt(result.toString())) <= 12 ){
							if(GMBInfoBundle.SetGpsDateMonth(tempInt) == 0)
								iTimeChange = 1;
						}
					}catch(NumberFormatException  e){
						Log.e(TAG, "===month speed input err===");
					}

					//day
					result.delete(0, result.length());
					result.append(String.format("%x", frameBuf.get() & 0xff));
					try{
						if((tempInt = Integer.parseInt(result.toString())) <= 31 ){
							if(GMBInfoBundle.SetGpsDateDay(tempInt) == 0)
								iTimeChange = 1;
						}
					}catch(NumberFormatException  e){
						Log.e(TAG, "===day speed input err===");
					}


					//judge over speed proc
					if(iRecordLastOverSpeedTime == 0)
						iRecordLastOverSpeedTime = Utils.OSTimeGet();
					if(Utils.XM_BUS){
						if(iAllowSpeed > 2)
							iAllowSpeed -= 2;
					}

					if(iNowSpeed > iAllowSpeed) {
						iRecordSpeed++;
						if(iRecordSpeed == iOverSpdAllowTime)
						{
							Log.i(TAG, "\n===Over Speed===");
							if(Utils.OSTimeGet()>(iRecordLastOverSpeedTime+60L*Utils.OS_TICKS_PER_SEC))
							{
								iRecordLastOverSpeedTime=Utils.OSTimeGet();
							}
						}

						if (iRecordSpeed >= iOverSpdAllowTime) {

						}
					}
					else {

						iRecordSpeed = 0;

					}
					break;
			}
		}catch(Exception e){
			return ER_SYSTEM_EXCEPTION;
		}

		return 0;
	}
} 